﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Intorise.Net;
using System.Net;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Intorise.Common;
using System.Text.RegularExpressions;
using Model;
using System.Globalization;
using System.Threading;
using Intorise.API;
using System.Windows.Forms;
using System.Drawing;
using System.IO;

namespace TestWindowsFormsApplication.Analyzer
{
    public class EmsAnalyzer : IFreightInfoAnalyse
    {
        public Action<string> RefreshAction;
        public Action<string> ShowMessageAction;
        static string lastGuid = "";
        static CookieContainer cookieContainer = new CookieContainer();
        Uri uri = new Uri("http://www.17track.net");
        public bool GetDataUndelived { get; set; }
        protected string TRACK_URL = "http://old.17track.net/r/handlertrack.ashx?callback=a&num={0}&pt=0&cm=0&cc=0&_={1}";//17track查询请求url
        protected NetTools tools = new NetTools(40);
        protected WebClient client = new WebClient();
        private Regex regex = new Regex(@"\d+");
        static int sleep = 30;//30秒

        public EmsAnalyzer()
        {
            //tools.Proxy = new WebProxy("proxy.mindray.corp");
            //tools.Proxy.Credentials = new NetworkCredential("80001339", "niJFZIUR");
            var request = tools.SendRequest("http://www.17track.net/zh-cn", "GET", cookieContainer);
            var response = request.GetResponse();
            var html = tools.GetResponseHtml(request);
            request.GetResponse().Close();
            ShowMessageAction = Program.MainForm.ShowMessageLine;
        }

        public virtual FreightInfo Analyse(string orderNo)
        {
            int delay = 0;
            int fc = 0;
        begin:
            delay++;
            var cookies = cookieContainer.GetCookies(uri);

            if (cookies == null || cookies.Count == 0)
            {
                if (cookies == null || cookies.Count == 0)
                {
                    cookieContainer.Add(uri, new Cookie("v5_TackingGuid", ""));
                    cookieContainer.Add(uri, new Cookie("__gads", "ID=9072cfd174e2c1ee:T=1449805897:S=ALNI_MatceB71J4DAAG310hecoTxPMJi6A"));
                    cookieContainer.Add(uri, new Cookie("_gat", "1"));
                    cookieContainer.Add(uri, new Cookie("v5_ShowedWelcome", "1"));
                    cookieContainer.Add(uri, new Cookie("_ga", "GA1.2.526659401.1449812572"));
                    cookieContainer.Add(uri, new Cookie("v5_Culture", "zh-cn"));
                    cookies = cookieContainer.GetCookies(uri);
                }
            }

            cookies["v5_TackingGuid"].Value = lastGuid;

            FreightInfo info = new FreightInfo();
            //string queryUrl = string.Format(TRACK_URL, orderNo, DateTime.Now.Ticks);////ems等查询
            string queryUrl = "http://www.17track.net/restapi/handlertrack.ashx";

            var request = tools.SendRequest(queryUrl, "POST", cookieContainer);
            request.Referer = "http://www.17track.net/zh-cn/track?nums=" + orderNo;
            tools.PostData("{\"guid\":\"\",\"data\":[{\"num\":\"" + orderNo + "\",\"fc\":\"" + fc + "\"}]}", request);
            var html = "";

            cookies["v5_TackingGuid"].Value = lastGuid;

            try
            {
                html = tools.GetResponseHtmlGzip(request);

            }
            catch (WebException ex)
            {
                client.DownloadString("http://www.17track.net/zh-cn");
                throw ex;
            }

            //var json = html.Remove(0, 2);
            //json = json.Remove(json.Length - 1, 1);
            var result = JsonConvert.DeserializeObject<Result>(html);
            lastGuid = result.G;
            request.Abort();
            if (result.Msg != "Ok" || result.dat.Count == 0)
            {
                switch (result.Ret)
                {
                    case -5:
                        info.Status = "查询过于频繁";
                        break;
                    case -8:
                        info.Status = "需要输入验证码";
                        break;
                    default:
                        info.Status = "重试";
                        break;
                }
                return info;
            }
            if (result.dat.First().Delay != 0)
            {
                if (delay > 2)
                {
                    info.Status = "重试:" + result.Msg; return info;
                }
                if (result.dat.First().Delay < 2)
                {
                    result.dat.First().Delay = 2;
                }
                ShowMessageAction("延迟：" + result.dat.First().Delay + " 秒后再试");
                Thread.Sleep(result.dat.First().Delay);
                goto begin;
            }

            if (result.dat.First().Track == null)
            {
                if (string.IsNullOrEmpty(result.dat.First().Yt))
                {
                    info.Status = "n";
                    info.ResultText = ""; return info;
                }
                else
                {
                    if (delay > 2)
                    {
                        info.Status = "重试:" + result.Msg; return info;
                    }
                    else
                    {
                        var ytItem = JsonConvert.DeserializeObject<YtClass>(result.dat.First().Yt);
                        fc = ytItem.D.FirstOrDefault();
                        goto begin;
                    }
                }
            }

            info.DeliveryCountryID = (int)result.dat.First().Track.C;
            info.ShipCountryID = (int)result.dat.First().Track.B;
            if (result.dat.First().Track.E != 40)//不等于40，未签收
            {
                info.Status = "n";
                if (GetDataUndelived)
                {

                }
                else if (result.dat.First().Track.Z0 == null || result.dat.First().Track.Z0.z == null || !result.dat.First().Track.Z0.z.Contains("Delivered"))//10、50为出现异常但也可能是正常签收
                {
                    return info;
                }
                else
                {
                    info.Status = "y";
                }
            }
            else
            {
                info.Status = "y";//已妥投
            }

            if (result.dat.First().Track.Z1 == null) { result.dat.First().Track.Z1 = new List<Item>(0); }
            if (result.dat.First().Track.Z2 == null) { result.dat.First().Track.Z2 = new List<Item>(0); }
            List<DateTime?> times = new List<DateTime?>(result.dat.First().Track.Z1.Count + result.dat.First().Track.Z2.Count);
            times.AddRange((from xx in result.dat.First().Track.Z1 select xx.a).ToList());
            times.AddRange((from xx in result.dat.First().Track.Z2 select xx.a).ToList());
            info.ShipDate = times.Min();
            if (GetDataUndelived)
            {
                info.ShipDate = times.Min();
                info.ResultText = result.dat.First().Track.Z1[0].d; return info;
            }

            if (result.dat.First().Track.Z2.Count > 0)
            {
                info.ResultText = GetResultString(result.dat.First().Track.Z2[0]);//取收件国数据
            }
            else if (result.dat.First().Track.Z0 != null)
            {
                info.ResultText = GetResultString(result.dat.First().Track.Z0);//取收件国数据
            }
            else
            {
                info.ResultText = "没有物流数据";
            }
            return info;

            #region 发往新西兰
            if (result.dat.First().Track.C == CountryEnum.新西兰)
            {
                if (result.dat.First().Track.Z1.Count > 1)
                {
                    info.ResultText = GetResultString(result.dat.First().Track.Z1[1]);
                }
                else
                {
                    info.ResultText = GetResultString(result.dat.First().Track.Z0);
                }
                return info;
            }
            #endregion
            #region 发往墨西哥
            if (result.dat.First().Track.C == CountryEnum.墨西哥)
            {
                if (result.dat.First().Track.Z2.Count > 0)
                {
                    info.ResultText = GetResultString(result.dat.First().Track.Z2[0]);
                }
                else
                {
                    info.ResultText = GetResultString(result.dat.First().Track.Z0);
                }
                return info;
            }
            #endregion
            if (result.dat.First().Track.B == CountryEnum.德国)
            {
                if (result.dat.First().Track.Z2.Count > 0)
                {
                    info.ResultText = GetResultString(result.dat.First().Track.Z2[0]); return info;
                }
            }
            if (result.dat.First().Track.B == CountryEnum.香港 && result.dat.First().Track.C == CountryEnum.瑞典)
            {
                if (result.dat.First().Track.Z2.Count > 1)
                {
                    info.ResultText = GetResultString(result.dat.First().Track.Z2[1]); return info;
                }
            }
            if (result.dat.First().Track.C == CountryEnum.挪威 || (result.dat.First().Track.B == CountryEnum.香港 && result.dat.First().Track.C == CountryEnum.丹麦))
            {
                if (result.dat.First().Track.Z2.Count > 1)
                {
                    info.ResultText = GetResultString(result.dat.First().Track.Z2[1]); return info;
                }
            }

            var last = orderNo.Substring(orderNo.Length - 2, 2).ToUpper();
            if ((last == "SG" || last == "HK" || last == "NL" || last == "GB")
                || result.dat.First().Track.C == CountryEnum.意大利 || result.dat.First().Track.C == CountryEnum.日本
                || result.dat.First().Track.B == CountryEnum.瑞典
                )
            {
                if (result.dat.First().Track.Z2.Count == 0)
                {
                    info.ResultText = GetResultString(result.dat.First().Track.Z0);
                }
                else
                {
                    info.ResultText = GetResultString(result.dat.First().Track.Z2[0]);
                }

                return info;
            }
            else if (result.dat.First().Track.C == CountryEnum.挪威 || (result.dat.First().Track.B == CountryEnum.香港 && result.dat.First().Track.C == CountryEnum.丹麦))
            {
                if (result.dat.First().Track.Z2.Count > 1)
                {
                    info.ResultText = GetResultString(result.dat.First().Track.Z2[1]); return info;
                }
            }

            #region RH开头去往英国的取收件第1条数据,RH开头去往瑞典的取收件第2条数据
            var first = orderNo.Substring(0, 2).ToUpper();
            if ((first == "RH" || first == "RI") && (result.dat.First().Track.C == CountryEnum.英国 && result.dat.First().Track.Z2.Count > 0))
            {
                info.ResultText = GetResultString(result.dat.First().Track.Z2[0]); return info;
            }
            if (first == "RH" && (result.dat.First().Track.C == CountryEnum.瑞典 && result.dat.First().Track.Z2.Count > 1))
            {
                info.ResultText = GetResultString(result.dat.First().Track.Z2[1]); return info;
            }
            #endregion

            List<Item> list = new List<Item>();
            info.ResultText = "";
            if (result.dat.First().Track.Z1.Count > 0)
            {
                list.Add(result.dat.First().Track.Z1[0]);
            }
            if (result.dat.First().Track.Z2.Count > 0)
            {
                list.Add(result.dat.First().Track.Z2[0]);
            }

            var item = list.OrderByDescending(x => x.a).FirstOrDefault();
            if (item == null)
            {
                info.ResultText = result.dat.First().Track.Z0.c + " " + result.dat.First().Track.Z0.d + " " + result.dat.First().Track.Z0.z;
            }
            else
            {
                info.ResultText = item.c + " " + item.d + " " + item.z;
            }

            return info;
        }

        public virtual List<FreightInfo> Analyse(List<string> orderNo)
        {
            List<FreightInfo> list = new List<FreightInfo>();

            var cookies = cookieContainer.GetCookies(uri);
            //9072cfd174e2c1ee:T
            if (cookies == null || cookies.Count == 0)
            {
                cookieContainer.Add(uri, new Cookie("v5_TackingGuid", ""));
                cookieContainer.Add(uri, new Cookie("__gads", "ID=9072cfd174e2c1ee:T=1449805897:S=ALNI_MatceB71J4DAAG310hecoTxPMJi6A"));
                cookieContainer.Add(uri, new Cookie("_gat", "1"));
                cookieContainer.Add(uri, new Cookie("v5_ShowedWelcome", "1"));
                cookieContainer.Add(uri, new Cookie("_ga", "GA1.2.526659401.1449812572"));
                cookieContainer.Add(uri, new Cookie("v5_Culture", "zh-cn"));
                cookies = cookieContainer.GetCookies(uri);
            }

            cookies["v5_TackingGuid"].Value = lastGuid;

            //string queryUrl = string.Format(TRACK_URL, orderNo, DateTime.Now.Ticks);////ems等查询
            string queryUrl = "http://www.17track.net/restapi/handlertrack.ashx";

            var request = tools.SendRequest(queryUrl, "POST", cookieContainer);
            request.Referer = "http://www.17track.net/zh-cn/track?nums=" + string.Join(",", orderNo);

            List<string> orders = new List<string>();
            for (var i = 0; i < orderNo.Count; i++)
            {
                orders.Add("{\"num\":\"" + orderNo[i] + "\"}");
            }

            string data = "{\"guid\":\"\",\"data\":[" + string.Join(",", orders) + "]}";
            tools.PostData(data, request);
            var html = "";
            try
            {
                html = tools.GetResponseHtmlGzip(request);
            }
            catch (WebException ex)
            {
                client.DownloadString("http://www.17track.net/zh-cn");
                throw ex;
            }

            //var json = html.Remove(0, 2);
            //json = json.Remove(json.Length - 1, 1);
            var result = JsonConvert.DeserializeObject<Result>(html);
            lastGuid = result.G;
            request.Abort();
            if (result.Msg != "Ok" || result.dat.Count == 0)
            {
                ShowMessageAction("获取数据失败：" + result.Msg);
                ShowMessageAction("等待：" + sleep + "秒");
                sleep += 5;
                RefreshAction(orders[0]);
                Thread.Sleep(sleep * 1000);
                return list;
            }
            result.dat.ForEach(x =>
            {
                FreightInfo info = new FreightInfo();
                list.Add(info);
                info.OrderNO = x.No;
                if (x.Track == null)
                {
                    info.Status = "n";
                    info.ResultText = "没有数据"; return;
                }
                if (x.Track.E != 40)//不等于40，未签收
                {
                    info.Status = "n";
                    if (GetDataUndelived)
                    {

                    }
                    else if (x.Track.E != 10 || x.Track.E != 50 || !x.Track.Z0.z.Contains("Delivered"))//10、50为出现异常但也可能是正常签收
                    {
                        return;
                    }
                    else
                    {
                        info.Status = "y";
                    }
                }
                else
                {
                    info.Status = "y";//已妥投
                }

                info.DeliveryCountryID = (int)x.Track.C;
                info.ShipCountryID = (int)x.Track.B;


                if (x.Track.Z1 == null) { x.Track.Z1 = new List<Item>(0); }
                if (x.Track.Z2 == null) { x.Track.Z2 = new List<Item>(0); }
                List<DateTime?> times = new List<DateTime?>(x.Track.Z1.Count + x.Track.Z2.Count);
                times.AddRange((from xx in x.Track.Z1 select xx.a).ToList());
                times.AddRange((from xx in x.Track.Z2 select xx.a).ToList());
                info.ShipDate = times.Min();
                if (GetDataUndelived)
                {
                    info.ShipDate = times.Min();
                    info.ResultText = x.Track.Z1[0].d; return;
                }

                if (x.Track.Z2.Count > 0)
                {
                    info.ResultText = GetResultString(x.Track.Z2[0]);//取收件国数据
                }
                else if (x.Track.Z0 != null)
                {
                    info.ResultText = GetResultString(x.Track.Z0);//取收件国数据
                }
                else
                {
                    info.ResultText = "没有物流数据";
                }
                return;

                #region 发往新西兰
                if (x.Track.C == CountryEnum.新西兰)
                {
                    if (x.Track.Z1.Count > 1)
                    {
                        info.ResultText = GetResultString(x.Track.Z1[1]);
                    }
                    else
                    {
                        info.ResultText = GetResultString(x.Track.Z0);
                    }
                    return;
                }
                #endregion
                #region 发往墨西哥
                if (x.Track.C == CountryEnum.墨西哥)
                {
                    if (x.Track.Z2.Count > 0)
                    {
                        info.ResultText = GetResultString(x.Track.Z2[0]);
                    }
                    else
                    {
                        info.ResultText = GetResultString(x.Track.Z0);
                    }
                    return;
                }
                #endregion
                if (x.Track.B == CountryEnum.德国)
                {
                    if (x.Track.Z2.Count > 0)
                    {
                        info.ResultText = GetResultString(x.Track.Z2[0]); return;
                    }
                }
                if (x.Track.B == CountryEnum.香港 && x.Track.C == CountryEnum.瑞典)
                {
                    if (x.Track.Z2.Count > 1)
                    {
                        info.ResultText = GetResultString(x.Track.Z2[1]); return;
                    }
                }
                if (x.Track.C == CountryEnum.挪威 || (x.Track.B == CountryEnum.香港 && x.Track.C == CountryEnum.丹麦))
                {
                    if (x.Track.Z2.Count > 1)
                    {
                        info.ResultText = GetResultString(x.Track.Z2[1]); return;
                    }
                }

                var last = x.No.Substring(x.No.Length - 2, 2).ToUpper();
                if ((last == "SG" || last == "HK" || last == "NL" || last == "GB")
                    || x.Track.C == CountryEnum.意大利 || x.Track.C == CountryEnum.日本
                    || x.Track.B == CountryEnum.瑞典
                    )
                {
                    if (x.Track.Z2.Count == 0)
                    {
                        info.ResultText = GetResultString(x.Track.Z0);
                    }
                    else
                    {
                        info.ResultText = GetResultString(x.Track.Z2[0]);
                    }

                    return;
                }
                else if (x.Track.C == CountryEnum.挪威 || (x.Track.B == CountryEnum.香港 && x.Track.C == CountryEnum.丹麦))
                {
                    if (x.Track.Z2.Count > 1)
                    {
                        info.ResultText = GetResultString(x.Track.Z2[1]); return;
                    }
                }

                #region RH开头去往英国的取收件第1条数据,RH开头去往瑞典的取收件第2条数据
                var first = x.No.Substring(0, 2).ToUpper();
                if ((first == "RH" || first == "RI") && (x.Track.C == CountryEnum.英国 && x.Track.Z2.Count > 0))
                {
                    info.ResultText = GetResultString(x.Track.Z2[0]); return;
                }
                if (first == "RH" && (x.Track.C == CountryEnum.瑞典 && x.Track.Z2.Count > 1))
                {
                    info.ResultText = GetResultString(x.Track.Z2[1]); return;
                }
                #endregion

                List<Item> items = new List<Item>();
                info.ResultText = "";
                if (x.Track.Z1.Count > 0)
                {
                    items.Add(x.Track.Z1[0]);
                }
                if (x.Track.Z2.Count > 0)
                {
                    items.Add(x.Track.Z2[0]);
                }

                var item = items.OrderByDescending(d => d.a).FirstOrDefault();
                if (item == null)
                {
                    info.ResultText = x.Track.Z0.c + " " + x.Track.Z0.d + " " + x.Track.Z0.z;
                }
                else
                {
                    info.ResultText = item.c + " " + item.d + " " + item.z;
                }
            });
            return list;
        }

        protected string GetResultString(Item item)
        {
            List<string> result = new List<string>(4);
            if (!string.IsNullOrEmpty(item.b))
            {
                result.Add(item.b);
            }
            if (!string.IsNullOrEmpty(item.c))
            {
                result.Add(item.c);
            }
            if (!string.IsNullOrEmpty(item.d))
            {
                result.Add(item.d);
            }
            if (!string.IsNullOrEmpty(item.z))
            {
                result.Add(item.z);
            }

            return string.Join(",", result);
        }
    }

    public class UpsAnalyzer : EmsAnalyzer
    {
        public UpsAnalyzer()
        {
            TRACK_URL = "http://old.17track.net/r/handlertrack.ashx?callback=a&num={0}&et=100002&_={1}";//ups查询请求url
        }
    }

    public class TntAnalyzer : EmsAnalyzer
    {
        public TntAnalyzer()
        {
            TRACK_URL = "http://old.17track.net/r/handlertrack.ashx?callback=a&num={0}&et=100004&_={1}";//tnt查询请求url
        }
    }

    public class DpdAnalyzer : EmsAnalyzer
    {
        public DpdAnalyzer()
        {
            TRACK_URL = "http://old.17track.net/r/handlertrack.ashx?callback=a&num={0}&et=100010&_={1}";//dpd查询请求url
        }
    }

    public class DpdNewAnalyzer : EmsAnalyzer
    {
        public DpdNewAnalyzer()
        {
            TRACK_URL = "http://old.17track.net/r/handlertrack.ashx?callback=a&num={0}&et=100007&_={1}";//dpd查询请求url
        }
    }

    public class AraAnalyzer : EmsAnalyzer
    {
        public AraAnalyzer()
        {
            TRACK_URL = "http://old.17track.net/r/handlertrack.ashx?callback=a&num={0}&et=100006&_={1}";//aramex查询请求url
        }
    }


    public class DhlAnalyzer : IFreightInfoAnalyse
    {
        string DHL_URL = "http://www.cn.dhl.com/shipmentTracking?AWB={0}&countryCode=cn&languageCode=zh&_={1}";//dhl查询请求url
        string DHL_URL_0 = "http://www.cn.dhl.com/shipmentTracking?countryCode=cn&fromDayValue={3}&fromMonthValue={2}&fromYearValue={1}&languageCode=zh&shipperReference={0}&toDayValue={6}&toMonthValue={5}&toYearValue={4}&_={7}";//dhl转单查询
        protected NetTools tools = new NetTools(30);
        protected WebClient client = new WebClient();

        public DhlAnalyzer()
        {
            //tools.Proxy = new WebProxy("proxy.mindray.corp");
        }

        public FreightInfo Analyse(string orderNo)
        {
            var queryUrl = string.Format(DHL_URL, orderNo, DateTime.Now.Ticks);//dhl 查询
            var info = dhlQuery(queryUrl);
            info.OrderType = OrderTypeEnum.DHL;
            if (info.Status == "没找到")
            {
                DateTime begin = DateTime.Now.AddMonths(-3);
                DateTime end = DateTime.Now;
                queryUrl = string.Format(DHL_URL_0, orderNo, begin.Year, begin.Month.ToString("").PadLeft(2, '0'), begin.Day.ToString().PadLeft(2, '0'), end.Year, end.Month.ToString().PadLeft(2, '0'), end.Day.ToString().PadLeft(2, '0'), DateTime.Now.ToFileTime());//dhl 查询
                info = dhlQuery(queryUrl);//转单查询
            }
            return info;
        }

        private FreightInfo dhlQuery(string queryUrl)
        {
            FreightInfo info = new FreightInfo();
            var request = tools.SendRequest(queryUrl, "GET");
            string html = tools.GetResponseHtml(request);
            JObject result = (JObject)JsonConvert.DeserializeObject(html);
            if (result["errors"] != null)
            {
                info.Status = "没找到"; return info;
            }
            if (result["results"].Count() == 0)
            {
                info.Status = "查询出错"; return info;
            }
            if (result["results"][0]["delivery"] == null || result["results"][0]["delivery"]["status"] == null)
            {
                info.Status = "查询出错"; return info;
            }
            if (result["results"][0]["delivery"]["status"].ToString() != "delivered")
            {
                info.Status = "n"; return info;
            }

            info = new FreightInfo();
            info.Status = "y";
            info.Deliveried = true;

            DateTime date = DateTime.MinValue;
            if (DateTime.TryParse(result["results"][0]["checkpoints"][((JArray)result["results"][0]["checkpoints"]).Count() - 1]["date"].ToString(), out date))
            {
                info.ShipDate = date;
            }
            info.ResultText = result["results"][0]["signature"]["label"] + " " + result["results"][0]["signature"]["signatory"] + " " + result["results"][0]["destination"]["value"];
            if (info.ResultText.Contains("快件通过第三方派送无法得到签收结果"))
            {
                return info;
            }
            //ELIZABETH, NJ - PALISADES PARK - USA
            var address = result["results"][0]["destination"]["value"].ToString();
            var items = address.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            address = items[items.Length - 1];
            items = address.Split(new char[] { '-' }, StringSplitOptions.RemoveEmptyEntries);

            if (items.Length > 0)
            {
                info.DeliveryCountryCode = items[items.Length - 1].Trim();
            }
            if (items.Length > 1)
            {
                info.DeliveryCity = items[items.Length - 2].Trim();
            }
            if (items.Length > 2)
            {
                info.DeliveryStateCode = items[items.Length - 3].Trim();
            }

            request.Abort();
            return info;
        }


        public List<FreightInfo> Analyse(List<string> orderNo)
        {
            throw new NotImplementedException();
        }
    }

    public class EcAnalyzer : IFreightInfoAnalyse
    {
        readonly string EC_URL = "http://www.ec-firstclass.org/Details.aspx";
        protected NetTools tools = new NetTools(30);
        protected WebClient client = new WebClient();

        public EcAnalyzer()
        {

        }

        public FreightInfo Analyse(string orderNo)
        {
            FreightInfo info = new FreightInfo();
            var request = tools.SendRequest(EC_URL, "POST");
            tools.PostData("TrackNums=" + orderNo, request);
            string html = tools.GetResponseHtmlGzip(request);
            var jsonText = Tools.SubString(html, "var result", "}]}");
            if (jsonText == "")
            {
                info.Status = "查询出错"; return info;
            }
            jsonText = Tools.SubString(jsonText, "{", "}]}");
            if (jsonText == "")
            {
                info.Status = "查询出错"; return info;
            }

            JObject result = (JObject)JsonConvert.DeserializeObject(jsonText);
            if (!(bool)result["Success"])
            {
                info.Status = "查询出错"; return info;
            }
            if (result["DetailInfos"].Count() == 0)
            {
                info.Status = "查询出错"; return info;
            }
            if (result["DetailInfos"][0]["Result"]["TrackSummmary"]["Status"] == null)
            {
                info.Status = "查询出错"; return info;
            }
            if (result["DetailInfos"][0]["Result"]["TrackSummmary"]["Status"].ToString() != "Delivered")
            {
                info.Status = "n"; return info;
            }
            if (result["DetailInfos"][0]["Result"]["TrackDetails"].Count() == 0)
            {
                info.Status = "查询出错"; return info;
            }
            info.Status = "y";

            var address = result["DetailInfos"][0]["Result"]["TrackSummmary"]["Address"];
            info.DeliveryCountry = address["Country"].LastOrDefault().ToString();
            var text = "妥投 " + address["City"] + "," + address["State"] + "," + address["Country"] + "," + address["Zip"];
            var trackDetails = result["DetailInfos"][0]["Result"]["TrackDetails"];
            text += " " + ((DateTime)trackDetails[trackDetails.Count() - 1]["Date"]).ToShortDateString();
            info = new FreightInfo { Deliveried = true };
            info.ResultText = text;
            request.Abort();
            return info;
        }


        public List<FreightInfo> Analyse(List<string> orderNo)
        {
            throw new NotImplementedException();
        }
    }

    public class RpxAnalyzer : IFreightInfoAnalyse
    {
        readonly string RPX_URL = "http://www.rpxonline.com/index.php?option=com_track&view=tracking";
        protected NetTools tools = new NetTools(30);
        protected WebClient client = new WebClient();
        Regex regex = new Regex("<div class=\"trace_column tc_date\">.+</div>");
        string tag = "<div class=\"trace_column tc_comment\">Comments</div>";
        string tag0 = "<div class=\"trace_column tc_comment\">";

        public RpxAnalyzer()
        {

        }

        public FreightInfo Analyse(string orderNo)
        {
            FreightInfo info = new FreightInfo();
            var request = tools.SendRequest(RPX_URL, "POST");
            tools.PostData("qType=T&sid=" + orderNo, request);
            string html = tools.GetResponseHtmlGzip(request);

            if (!html.Contains("Delivered"))
            {
                info.Status = "n"; return info;
            }

            int index = html.IndexOf(tag);
            if (index < 0)
            {
                info.Status = "查询出错"; return info;
            }

            index += tag.Length;

            int deliveredIndex = html.IndexOf(tag0, index);
            if (deliveredIndex < 0)
            {
                info.Status = "查询出错"; return info;
            }
            deliveredIndex += tag0.Length;

            int end = html.IndexOf("</div>", deliveredIndex);
            if (end < 0)
            {
                info.Status = "查询出错"; return info;
            }

            info.ResultText = html.Substring(deliveredIndex, end - deliveredIndex).Trim();
            info.Status = "y";

            var matchs = regex.Matches(html, end);
            Match[] matchArray = new Match[matchs.Count];
            matchs.CopyTo(matchArray, 0);
            List<DateTime> dates = new List<DateTime>();
            DateTime datetime;
            foreach (Match m in matchArray)
            {
                if (m.Success)
                {
                    if (DateTime.TryParse(m.Value.Replace("<div class=\"trace_column tc_date\">", "").Replace("</div>", ""), out datetime))
                    {
                        dates.Add(datetime);
                    }
                }
            }
            info.ShipDate = dates.Min<DateTime>();
            request.Abort();
            return info;
        }


        public List<FreightInfo> Analyse(List<string> orderNo)
        {
            throw new NotImplementedException();
        }
    }

    public class FedexAnalyzer : IFreightInfoAnalyse
    {
        readonly string FEDEX_URL = "https://www.fedex.com/trackingCal/track?action=trackpackages&locale=zh_CN&version=1&format=json&data={%22TrackPackagesRequest%22:{%22appType%22:%22WTRK%22,%22uniqueKey%22:%22%22,%22processingParameters%22:{},%22trackingInfoList%22:[{%22trackNumberInfo%22:{%22trackingNumber%22:%22<ORDERNO>%22,%22trackingQualifier%22:%22%22,%22trackingCarrier%22:%22%22}}]}}&_=";
        protected NetTools tools = new NetTools(30);
        protected WebClient client = new WebClient();

        public FedexAnalyzer()
        {

        }

        public FreightInfo Analyse(string orderNo)
        {
            FreightInfo info = new FreightInfo { Status = "n" };
            string url = FEDEX_URL.Replace("<ORDERNO>", orderNo);
            var request = tools.SendRequest(url + DateTime.Now.Ticks, "GET");
            string html = tools.GetResponseHtmlGzip(request);

            JObject result = (JObject)JsonConvert.DeserializeObject(html);
            var data = result["TrackPackagesResponse"]["packageList"];
            if (data.Count() == 0)
            {
                return info;
            }
            data = data[0];
            if (data["keyStatus"].ToString() != "已送达")
            {
                return info;
            }
            var text = data["statusWithDetails"].ToString();
            int index = text.IndexOf("签收人");
            text = text.Substring(index);
            text += " " + ((DateTime)data["shipDt"]).ToShortDateString();

            info.Status = "y";
            info.ResultText = text;
            request.Abort();
            return info;
        }


        public List<FreightInfo> Analyse(List<string> orderNo)
        {
            throw new NotImplementedException();
        }
    }

    public class AusAnalyzer : IFreightInfoAnalyse
    {
        readonly string AUSPOST_URL = "http://auspost.com.au/track/track.html?exp=b";
        protected NetTools tools = new NetTools(30);
        protected WebClient client = new WebClient();
        Regex ausLocationRegex = new Regex(@"<div class=""cell-float-right ed-location"">\s+<p>(.*)</p>\s+</div>");
        Regex ausSubmitDateRegex = new Regex(@"<div class=""cell-float-left ed-date"">\s+<p>\s+(.*)\s+</p>\s+</div>");
        Regex regex_p = new Regex("<p>.*</p>");

        public AusAnalyzer()
        {

        }

        public FreightInfo Analyse(string orderNo)
        {
            FreightInfo info = new FreightInfo { Status = "n" };
            var request = tools.SendRequest(AUSPOST_URL, "POST");
            tools.PostData("trackIds=" + orderNo, request);
            string html = tools.GetResponseHtmlGzip(request);

            if (html.Contains("Invalid tracking number"))
            {
                return info;
            }
            int index = html.IndexOf("<p>Delivered</p>");
            if (index < 0)
            {
                info.Status = "n"; return info;
            }
            info.Status = "y";
            info.ResultText = "Delivered";
            index = html.IndexOf("<div id=\"more-details-content\">");
            if (index < 0) { return info; }

            var matchs = ausLocationRegex.Matches(html, index);
            if (matchs.Count > 0)
            {
                if (matchs[0].Success)
                {
                    info.ResultText += "，" + matchs[0].Groups[1].Value;
                }
            }
            matchs = ausSubmitDateRegex.Matches(html, index);
            if (matchs.Count > 0)
            {
                if (matchs[matchs.Count - 1].Success)
                {
                    info.ResultText += "，" + matchs[matchs.Count - 1].Groups[1].Value;
                }
            }

            request.Abort();
            return info;
        }


        public List<FreightInfo> Analyse(List<string> orderNo)
        {
            throw new NotImplementedException();
        }
    }

    public class HyexpAnalyzer : IFreightInfoAnalyse
    {
        readonly string POST_URL = "http://www.hyexp.net/cgi-bin/GInfo.dll?EmmisTrackE";
        protected NetTools tools = new NetTools(30);
        protected WebClient client = new WebClient();
        Regex statusRegex = new Regex(@"<span id='HeaderState'><br>Status \: ([^<]*)</span>");
        Regex signedRegex = new Regex(@"<span id='HeaderSign'><br>Signed for by \: ([^<]*)</span>");
        Regex submitDateRegex = new Regex(@"<td align='center' bgcolor='#F5F9FA' class='trackListOdd'>([^</td>]*)</td>");

        public HyexpAnalyzer()
        {

        }

        public FreightInfo Analyse(string orderNo)
        {
            FreightInfo info = new FreightInfo { Status = "n" };
            var request = tools.SendRequest(POST_URL, "POST");
            tools.PostData("w=jxhyexp&cno=" + orderNo, request);
            string html = tools.GetResponseHtml(request);

            int index = 0;
            var matchs = statusRegex.Matches(html);
            if (matchs.Count == 0 || !matchs[0].Success || matchs[0].Groups[1].Value.IndexOf("Delivered") < 0)
            {
                return info;
            }
            info.Status = "y";
            index = matchs[0].Index;

            matchs = signedRegex.Matches(html, index);
            if (matchs.Count > 0 && matchs[0].Success)
            {
                info.ResultText += matchs[0].Groups[1].Value;
                index = matchs[0].Index;
            }

            matchs = submitDateRegex.Matches(html, index);
            DateTime time = DateTime.Now;
            DateTime shipDate = DateTime.Now;

            foreach (Match match in matchs)
            {
                if (DateTime.TryParse(match.Groups[1].Value, out time))
                {
                    if (shipDate.CompareTo(time) > 0)
                    {
                        shipDate = time;
                        info.ShipDate = time;
                    }
                }
            }

            request.Abort();
            return info;
        }


        public List<FreightInfo> Analyse(List<string> orderNo)
        {
            throw new NotImplementedException();
        }
    }

    public class SgxAnalyzer : IFreightInfoAnalyse
    {
        readonly string POST_URL = "http://www.sgx-th.com/cgi-bin/GInfo.dll?EmmisTrackJ";
        protected NetTools tools = new NetTools(30);
        protected WebClient client = new WebClient();
        Regex statusRegex = new Regex(@"配達状況：([^<]*)<");
        Regex timeRegex = new Regex(@"<td align='center' bgcolor='[^']+' class='[^']+'>([^</td>]*)</td>");
        Regex infoRegex = new Regex(@"<td align='left' bgcolor='[^']+' class='[^']+'>([^</td>]*)</td>");

        public FreightInfo Analyse(string orderNo)
        {
            FreightInfo info = new FreightInfo { Status = "n" };
            var request = tools.SendRequest(POST_URL, "POST");
            tools.PostData("cno=" + orderNo + "&w=sgx-th", request);
            string html = tools.GetResponseHtml(request, Encoding.GetEncoding("gb2312"));

            int index = 0;
            var matchs = statusRegex.Matches(html);
            if (matchs.Count == 0 || !matchs[0].Success || matchs[0].Groups[1].Value != "配達完了")
            {
                return info;
            }
            info.Status = "y";
            index = matchs[0].Index;

            List<DateTime> dates = new List<DateTime>();
            DateTime time;
            matchs = timeRegex.Matches(html, index);
            for (int i = 0; i < matchs.Count; i++)
            {
                if (DateTime.TryParse(matchs[i].Groups[1].Value, out time))
                {
                    dates.Add(time);
                }
            }

            info.ShipDate = dates.Min();

            matchs = infoRegex.Matches(html, index);
            if (matchs.Count > 1)
            {
                info.ResultText = matchs[matchs.Count - 2].Groups[1].Value;
            }
            request.Abort();
            return info;
        }


        public List<FreightInfo> Analyse(List<string> orderNo)
        {
            throw new NotImplementedException();
        }
    }

    public class FourPXAnalyzer : IFreightInfoAnalyse
    {
        readonly string POST_URL = "https://ws01.ffdx.net/v4/etrack_blank.aspx/WS_Header_SearchTrack_Extended2";
        readonly string RefererURL = "https://ws01.ffdx.net/v4/etrack_blank.aspx?stid=airpak&txtinput=hide&ifr=y&version=dpex&cn={0}";
        protected NetTools tools = new NetTools(30);
        protected WebClient client = new WebClient();
        Regex timeRegex = new Regex("<td>([^</td>]*)</td>");

        public FourPXAnalyzer()
        {
            //tools.Proxy = new WebProxy("proxy.mindray.corp");
            //tools.Proxy.Credentials = new NetworkCredential("80000708", "mindray1234!");
        }

        public FreightInfo Analyse(string orderNo)
        {
            FreightInfo info = new FreightInfo { Status = "n" };
            CookieContainer cookie = new CookieContainer();
            var request = tools.SendRequest(string.Format(RefererURL, orderNo), "GET", cookie);
            request.Referer = RefererURL;
            string html = tools.GetResponseHtmlGzip(request);

            request = tools.SendRequest(string.Format(POST_URL, orderNo), "GET", cookie);
            request.Referer = RefererURL;
            request.ContentType = "application/json; charset=UTF-8";
            tools.PostData("{\"trackconnote\":\"" + orderNo + "\",\"viewtype\":\"aview\",\"stid\":\"airpak\",\"OptionalField\":\"\"}", request);

            //tools.PostData("trackconnote=" + orderNo + "&viewtype=aview&stid=airpak&OptionalField=", request);
            html = tools.GetResponseHtml(request);
            var item = JsonConvert.DeserializeObject(html);
            var result = Tools.SubString(item.ToString(), "<table class='sortable' id='trackresult'", "</table>");
            if (!result.Contains("Delivered"))
            {
                return info;
            }
            info.Status = "y";

            var matches = timeRegex.Matches(result);
            if (matches.Count > 1)
            {

                info.ShipDate = DateTime.Parse(matches[matches.Count - 2].Groups[1].Value, new CultureInfo("en-US"));
            }
            //info.ResultText = "Proof of Delivery ";
            request.Abort();
            var index = html.IndexOf("Signed By : ");
            if (index > -1)
            {
                html = html.Substring(index, html.Length - index);
                info.ResultText += "  " + Tools.SubString(html, "\\u003cstrong\\u003e", "\\u003c/strong\\u003e", true);
            }
            return info;
        }


        public List<FreightInfo> Analyse(List<string> orderNo)
        {
            throw new NotImplementedException();
        }
    }

    public class FourPXENAnalyzer : IFreightInfoAnalyse
    {
        readonly string POST_URL = "http://en.4px.com/index.php?option=com_tracking4px";
        readonly string RefererURL = "http://en.4px.com/index.php?option=com_tracking4px";
        protected NetTools tools = new NetTools(30);
        protected WebClient client = new WebClient();
        Regex timeRegex = new Regex(@"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}", RegexOptions.Singleline);
        Regex destinationRegex = new Regex("<td align=\"center\" class=\"t2_chaxun2\">([\\S\\s]*?)</td>", RegexOptions.Singleline);
        Regex deliveredRegex = new Regex("<div align=\"center\">\\s*?(已送达|妥投[^<]*)[\\S\\s]*?</div>");

        public FreightInfo Analyse(string orderNo)
        {
            FreightInfo info = new FreightInfo { Status = "n" };
            var request = tools.SendRequest(string.Format(POST_URL, orderNo), "POST");
            request.Referer = RefererURL;
            tools.PostData("trackno=" + orderNo, request);
            string html = tools.GetResponseHtmlGzip(request);

            int index = html.IndexOf("Latest status", StringComparison.OrdinalIgnoreCase);
            if (index < 0) { return info; }

            var matche = deliveredRegex.Match(html);

            if (!matche.Success)
            {
                return info;
            }

            info.Status = "y";
            var match = destinationRegex.Match(html, index);
            if (match.Success)
            {
                info.ResultText += match.Groups[1].Value.Replace("&nbsp;", "") + " " + matche.Groups[1].Value;
            }

            var matches = timeRegex.Matches(html, index);
            if (matches.Count > 0)
            {
                DateTime time;
                if (DateTime.TryParse(matches[matches.Count - 1].Value, out time))
                {
                    info.ShipDate = time;
                }
            }
            return info;
        }


        public List<FreightInfo> Analyse(List<string> orderNo)
        {
            throw new NotImplementedException();
        }
    }

    public class UspsAnalyzer : IFreightInfoAnalyse
    {
        readonly string POST_URL = "https://tools.usps.com/go/TrackConfirmAction.action?tRef=fullpage&tLc=1&text28777=&tLabels={0}";
        protected NetTools tools = new NetTools(30);
        protected WebClient client = new WebClient();
        Regex timeRegex = new Regex("<td class=\"date-time\">\\s+<p>\\s+(.+)");

        public FreightInfo Analyse(string orderNo)
        {
            FreightInfo info = new FreightInfo { Status = "n" };
            var request = tools.SendRequest(string.Format(POST_URL, orderNo), "GET");
            string html = tools.GetResponseHtmlGzip(request);

            var tag = "<h2 class=\"hide-fromsighted\">";
            int begin = html.IndexOf(tag);
            if (begin < 0) { return info; }
            int end = html.IndexOf("</h2>", begin + tag.Length);
            if (end < 0) { return info; }

            var status = html.Substring(begin + tag.Length, end - begin - tag.Length);
            if (status == null || status.ToLower() != "delivered")
            {
                return info;
            }

            //<p class="tracking-summary-details" id="LabelSummaryDetails-9274899996329701693606">...</p>
            //<p class="tracking-summary-details" id="LabelSummaryDetails-9274899996329701659169">...</p>
            tag = string.Format("<p class=\"tracking-summary-details\" id=\"LabelSummaryDetails-{0}\">", orderNo);
            begin = html.IndexOf(tag);
            if (begin < 0) { return info; }
            end = html.IndexOf("</p>", begin + tag.Length);
            if (end < 0) { return info; }

            info.Status = "y";
            info.ResultText = html.Substring(begin + tag.Length, end - begin - tag.Length).Trim(new char[] { '\r', '\n' });
            var matches = timeRegex.Matches(html);
            if (matches.Count > 0)
            {
                info.ShipDate = DateTime.Parse(matches[matches.Count - 1].Groups[1].Value);
            }
            return info;
        }


        public List<FreightInfo> Analyse(List<string> orderNo)
        {
            throw new NotImplementedException();
        }
    }

    public class DongAnalyzer : IFreightInfoAnalyse
    {
        readonly string URL = "http://www.dongbups.com/newHtml/main.jsp";
        readonly string POST_URL = "https://www.dongbups.com/newHtml/delivery/dvsearch.jsp";
        readonly string POST_URL0 = "https://www.dongbups.com/newHtml/delivery/dvsearch_View.jsp";

        protected NetTools tools = new NetTools(30);
        protected WebClient client = new WebClient();
        Regex regex = new Regex(@"<td  align=\""center\"">([^</td>]*)</td>");
        Regex regex0 = new Regex("<td>([^</td>]*)</td>");

        public FreightInfo Analyse(string orderNo)
        {
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
            FreightInfo info = new FreightInfo { Status = "n" };
            CookieContainer cookie = new CookieContainer();
            var request = tools.SendRequest(URL, "GET", cookie);
            string html = tools.GetResponseHtml(request);

            request = tools.SendRequest(POST_URL, "POST", cookie);
            tools.PostData("mode=SEARCH&search_type=1&sellNum=&sYMD=&eYMD=&search_item_no=" + orderNo, request);
            html = tools.GetResponseHtml(request, Encoding.GetEncoding("EUC-KR"));
            //html = tools.GetResponseHtml(request);

            int begin = html.LastIndexOf(orderNo);
            if (begin < 0) { return info; }

            var matches = regex.Matches(html, begin);

            if (matches.Count > 0)
            {
                info.Status = "y";
            }
            else
            {
                return info;
            }

            info.ResultText = "";
            if (matches.Count > 2)
            {
                info.ResultText += matches[2].Value.Replace("<td  align=\"center\">", "").Replace("</td>", "") + " ";
            }
            if (matches.Count > 3)
            {
                info.ResultText += matches[3].Value.Replace("<td  align=\"center\">", "").Replace("</td>", "") + " ";
            }

            request = tools.SendRequest(POST_URL0, "POST", cookie);
            tools.PostData("item_no=" + orderNo, request);
            html = tools.GetResponseHtml(request, Encoding.GetEncoding("EUC-KR"));
            //html = tools.GetResponseHtml(request);
            begin = html.IndexOf("listns");
            if (begin < 0)
            {
                return info;
            }
            matches = regex0.Matches(html, begin);
            DateTime time;
            for (var i = 0; i < matches.Count; i++)
            {
                var td = matches[i].Value.Replace("<td>", "").Replace("</td>", "");
                if (DateTime.TryParse(td, out time))
                {
                    info.ResultText += td;
                    break;
                }
            }
            return info;
        }


        public List<FreightInfo> Analyse(List<string> orderNo)
        {
            throw new NotImplementedException();
        }
    }

    public class RoyalAnalyzer : IFreightInfoAnalyse
    {
        readonly string URL = "https://www.royalmail.com/track-your-item";

        protected NetTools tools = new NetTools(30);
        protected WebClient client = new WebClient();
        Regex regex = new Regex(@"<input type=""hidden"" name=""form_build_id""([^/>]*)/>");
        Regex regex0 = new Regex(@"<input type=""hidden"" name=""time_token"" id=""edit-time-token"" value=""([^\""]*)");
        Regex regex1 = new Regex("<td>([^</td>]*)</td>");

        public FreightInfo Analyse(string orderNo)
        {
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
            FreightInfo info = new FreightInfo { Status = "n" };
            CookieContainer cookie = new CookieContainer();
            var request = tools.SendRequest(URL, "GET", cookie);
            string html = tools.GetResponseHtmlGzip(request);

            var matches = regex.Matches(html);
            var form_build_id = "";
            if (matches.Count > 2)
            {
                form_build_id = Tools.SubString(matches[1].Value, "value=\"", "\"", true);
            }
            else
            {
                return info;
            }

            var time_token = "";
            matches = regex0.Matches(html);
            if (matches.Count > 0)
            {
                time_token = Tools.SubString(matches[0].Value, "value=\"", true);
            }
            else
            {
                return info;
            }



            request = tools.SendRequest(URL, "POST", cookie);
            tools.PostData("tracking_number=" + orderNo + "&op=Track+item&time_token=" + time_token + "&form_build_id=" + form_build_id + "&form_id=rml_track_trace_search_form", request);
            html = tools.GetResponseHtmlGzip(request);
            //html = tools.GetResponseHtml(request);

            if (html.IndexOf("DELIVERED", StringComparison.Ordinal) < 0)
            {
                return info;
            }
            info.Status = "y";

            var tag = "<p>Status: <span class=\"strong\">Delivered</span></p>";
            int begin = html.IndexOf(tag);
            if (begin < 0) { return info; }

            begin = html.IndexOf("<p>", begin + tag.Length);
            if (begin < 0) { return info; }
            int end = html.IndexOf("</p>", begin + 3);
            if (end < 0) { return info; }

            info.ResultText = html.Substring(begin + 3, end - begin - 3);

            tag = "<table class=\"sticky-enabled\">";
            var tag0 = "</table>";
            begin = html.IndexOf(tag);
            end = html.IndexOf(tag0, begin + tag.Length);
            var details = html.Substring(begin + tag.Length, end - begin - tag.Length);

            matches = regex1.Matches(details);
            if (matches.Count > 3)
            {
                DateTime time;
                var value = matches[matches.Count - 3].Value;
                value = value.Replace("<td>", "").Replace("</td>", "");
                if (DateTime.TryParse(value, out time))
                {
                    info.ResultText += "  " + time.ToString();
                }
            }
            return info;
        }


        public List<FreightInfo> Analyse(List<string> orderNo)
        {
            throw new NotImplementedException();
        }
    }

    public class CnexpAnalyzer : IFreightInfoAnalyse
    {
        readonly string URL = "http://tracking.cnexps.com/cgi-bin/GInfo.dll?EmmisTracke";

        protected NetTools tools = new NetTools(30);
        protected WebClient client = new WebClient();
        Regex regex = new Regex("<td align='center' bgcolor='#F5F9FA' class='trackListOdd'>([^</td>]*)</td>");

        public FreightInfo Analyse(string orderNo)
        {
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
            FreightInfo info = new FreightInfo { Status = "n" };
            var request = tools.SendRequest(URL, "POST");
            tools.PostData("w=cnexx&ntype=10%2F&cno=" + orderNo, request);
            var html = tools.GetResponseHtml(request);
            //html = tools.GetResponseHtml(request);

            var status = Tools.SubString(html, "<span id='HeaderState'><br>Status :", "</span>", true);
            if (status.Trim() == "Delivered")
            {
                info.Status = "y";
            }
            else
            {
                return info;
            }

            info.ResultText = Tools.SubString(html, "Destination :", "</span>", true);

            info.ResultText += " " + Tools.SubString(html, "<span id='HeaderSign'><br>", "</span>", true);

            var matches = regex.Matches(html);
            if (matches.Count > 0)
            {
                DateTime time;
                var value = matches[matches.Count - 1].Value;
                value = value.Replace("<td align='center' bgcolor='#F5F9FA' class='trackListOdd'>", "").Replace("</td>", "");
                if (DateTime.TryParse(value, out time))
                {
                    info.ResultText += "  " + time.ToString();
                }
            }
            return info;
        }


        public List<FreightInfo> Analyse(List<string> orderNo)
        {
            throw new NotImplementedException();
        }
    }

    public class JsExpENAnalyzer : IFreightInfoAnalyse
    {
        readonly string POST_URL = "http://121.41.92.144/cgi-bin/GInfo.dll?EmmisTrack";
        readonly string RefererURL = "http://www.js-exp.com/cgi-bin/GInfo.dll?EmmisTrack";
        protected NetTools tools = new NetTools(30);

        Regex tableRegex = new Regex(@"<div id='oDetail'>(.*?)</div>", RegexOptions.Singleline);
        Regex dateRegex = new Regex(@"<td [^>]+>(.*?)</td>", RegexOptions.Singleline);
        //Regex timeRegex = new Regex(@"<td class=\""t1_chaxun2\"">([^(</td>)]*)</td>");

        public JsExpENAnalyzer()
        {
            //tools.Proxy = new WebProxy("proxy.mindray.corp");
            //tools.Proxy.Credentials = new NetworkCredential("80000708", "mindray1234!");
        }

        public FreightInfo Analyse(string orderNo)
        {
            FreightInfo info = new FreightInfo { Status = "n" };
            var request = tools.SendRequest(string.Format(POST_URL, orderNo), "POST");
            request.Referer = RefererURL;
            tools.PostData("nredir=1&w=js-exp&cno=" + orderNo + "&cmodel=track&ntype=1", request);
            string html = tools.GetResponseHtml(request, Encoding.GetEncoding("gb2312"));

            var status = Tools.SubString(html, "状    态：", "</span>", true);
            if (string.IsNullOrEmpty(status)) { return info; }

            if (status == "送达！")
            {
                info.Status = "y";
            }
            var countryText = Tools.SubString(html, "目 的 地：", "</span>", true);
            info.CountryModel = LuluHelper.GetCountryByNameCN(countryText);
            var match = tableRegex.Match(html);
            if (!match.Success)
            {
                return info;
            }
            var matches = dateRegex.Matches(match.Value);

            if (matches.Count == 0)
            {
                return info;
            }

            DateTime time;
            if (DateTime.TryParse(matches[3].Groups[1].Value, out time))
            {
                info.ShipDate = time;
            }
            info.ResultText += matches[matches.Count - 2].Groups[1].Value + " " + Tools.SubString(html, "签 收 人：", "</span>", true);
            return info;
        }


        public List<FreightInfo> Analyse(List<string> orderNo)
        {
            throw new NotImplementedException();
        }
    }

    public class PodtrackAnalyzer : IFreightInfoAnalyse
    {
        readonly string POST_URL = "http://118.139.183.89/podtrack/details.aspx?ID={0}";
        protected NetTools tools = new NetTools(30);

        Regex dateRegex = new Regex(@"<span[^>]+>(.*?)</span>", RegexOptions.Singleline);
        //Regex timeRegex = new Regex(@"<td class=\""t1_chaxun2\"">([^(</td>)]*)</td>");

        public PodtrackAnalyzer()
        {
            //tools.Proxy = new WebProxy("proxy.mindray.corp");
            //tools.Proxy.Credentials = new NetworkCredential("80000708", "mindray1234!");
        }

        public FreightInfo Analyse(string orderNo)
        {
            FreightInfo info = new FreightInfo { Status = "n" };
            var request = tools.SendRequest(string.Format(POST_URL, orderNo), "GET");

            string html = tools.GetResponseHtml(request);

            string tag = "<span id=\"lblStatus\" style=\"vertical-align:top\">  :  Shipment Delivered</span>";
            int index = html.IndexOf(tag);
            if (index < 0)
            {
                return info;
            }
            index += tag.Length;

            info.Status = "y";
            info.ResultText = Tools.SubString(html, "<span id=\"lblSignedby\" style=\"vertical-align:top\">  :", "</span>", true);

            var text = Tools.SubString(html, "<table class=\"Text\"", "</table>", true);
            var matches = dateRegex.Matches(text);


            if (matches.Count > 2)
            {
                info.ResultText += "," + matches[2].Groups[1].Value;
            }

            if (matches.Count > 3)
            {
                DateTime time;
                if (DateTime.TryParse(matches[matches.Count - 4].Groups[1].Value, out time))
                {
                    info.ShipDate = time;
                }
            }
            return info;
        }


        public List<FreightInfo> Analyse(List<string> orderNo)
        {
            throw new NotImplementedException();
        }
    }
}
